module baremetal.volatile;


/**
* 寄存器读写操作
*/
pragma(inline, true)
struct volatile(T)
{
    import core.atomic;
    private shared(T) _storage;

    @disable this();
    /// 读取寄存器值
    @property 
    T value() const
    {
        return atomicLoad(_storage);
    }
    alias value this;
    /// 直接送出原始状态
    @property 
    ref T orig() => cast(T)_storage;
    /// 获取指针
    @property
    T* ptr() const
    {
        return cast(T*)&_storage;
    }
    /// 重载
    void opOpAssign(string op)(in T rhs) 
    {
        atomicOp!(op~"=")(_storage, rhs);
    }
    void opAssign()(const T rhs)
    {
        atomicStore(_storage, rhs);
    }
    bool opEquals()(const T rhs) const
    {
        return atomicOp!`==`(_storage,rhs) != 0;
    }
    int opCmp()(const T rhs) const
    {
        return atomicOp!"=="(_storage, rhs);        
    }
    /// `$` 常量定义
    @property int opDollar(size_t dim : 0)() 
    { 
        return (this.sizeof*8) - 1; 
    }
    @property int opIndex(size_t pos)
    {
        return (atomicLoad(_storage) >> pos) & 1;
    }
    @property void  opIndexAssign(T v,size_t pos)
    {
        if(v)
            atomicOp!`|=`(_storage, 1 << pos);
        else
            atomicOp!`&=`(_storage, ~(1 << pos));
    }
    /// 位域取值 `=[1..5]`
    T opSlice(size_t l,size_t h)
    in(l<=h)
    in(h < T.sizeof*8)
    {
        auto ret = this.value;
        ret <<= h;              /// 去除无效位信息
        ret >>= (h+l);          /// 对齐0位
        return ret; 
    }
    /// 位域赋值 `[1..5]=v`
    void opSliceAssign(T v, size_t l, size_t h)
    in(l<=h)
    in(h < T.sizeof*8)
    in(v <= (MakerMask(l,h) >> l))
    {
        auto mask = MakerMask(l,h);
        atomicOp!`&=`(_storage, ~mask);
        atomicOp!`|=`(_storage, (v << l));
    }

}